---
id: countdown
title: CSS 实现动感的倒计时效果
description: property 实现数字动效倒计时
---

import {
  CountDownDemo1,
  CountDownDemo2,
  CountDownDemo3
} from "@site/src/docsDemo/Countdown";

## 数字的变化

在以前，数字的变化可能需要创建多个标签，然后改变位移来实现

```html
<div>
  <span>5</span>
  <span>4</span>
  <span>3</span>
  <span>2</span>
  <span>1</span>
</div>
```

这种方式需要创建多个标签，略微繁琐，也不易扩展。现在有更简洁的方式可以实现了，那就是 CSS [`@property`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property)。这是干什么的呢？简单来讲，可以自定义属性，在这个例子中，**可以让数字像颜色一样进行过渡和动画**，可能不太懂，直接看例子吧

假设 HTML 是这样的

```html
<!-- --t 自定义变量，可在css中通过var 引用 -->
<div id="countdown" style="--t: 5"></div>
```

然后我们通过 CSS 变量将数字渲染到页面，这里需要借助伪元素和计数器

```css showLineNumbers
#countdown::after {
  counter-reset: time var(--t);
  content: counter(time);
}
```

### 演示

<BrowserWindow>
  <CountDownDemo1 />
</BrowserWindow>

如何让这个数字变化呢？既然要有变化，肯定少不了 css 动画，修改后的 css 如下

```css {8-13,15-18} showLineNumbers
.countdown2 {
  font-size: 60px;
  &::after {
    --t: 5;
    counter-reset: time var(--t);
    content: counter(time);
  }
  &.start {
    &::after {
      animation: count 5s forwards;
    }
  }
}

@keyframes count {
  to {
    --t: 0;
  }
}
```

#### 演示

<BrowserWindow>
  <CountDownDemo2 />
</BrowserWindow>

现在的效果仅仅是 5 秒后，数字从 5 变成了 0，并没有` 5 => 4 => 3 => 2 => 1` 这种阶段变化。然后最重要的一步来了，加上以下自定义属性

## [@property](https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property)

@property CSS at-rule 是 CSS Houdini API 的一部分，它允许开发者显式地定义他们的 css 自定义属性, 允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承。

@property 规则提供了一个直接在样式表中注册自定义属性的方式，而无需运行任何 JS 代码。有效的 @property 规则会注册一个自定义属性，就像 CSS.registerProperty (en-US) 函数被使用同样的参数调用了一样。

```css
@property --t {
  syntax: "<integer>";
  inherits: false;
  initial-value: 0;
}
```

也可以使用 js 的方式添加自定义属性

```js
window.CSS.registerProperty({
  name: "--mytimer",
  syntax: "<integer>",
  inherits: false,
  initialValue: 5
});
```
### 演示
<BrowserWindow>
  <CountDownDemo3 />
</BrowserWindow>

是不是很神奇？可以这么理解，通过@property 定义后，这个变量--mytimer 本身可以单独设置动画了，就像颜色变化一样。

另外，使用计数器的好处是可以随意更换类型，比如将上面的阿拉伯数字换成中文计数，只需要更换计数器类型就行了

## 参考资料

https://mp.weixin.qq.com/s/1NP0xsn1kAWrsC3Ajj9ijw

